package com.hecate.common.bid;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author 黄星星
 * @date 2020-12-09
 */
public class SegmentGen {
    private static final int MAX_ID = 999999;
    private static final int MAX_LENGTH = 32;
    private static ThreadLocal<DecimalFormat> threadLocalDecimalFormat = ThreadLocal.withInitial(() -> {
        return new DecimalFormat();
    });
    private static ThreadLocal<SimpleDateFormat> threadLocalFormatter = ThreadLocal.withInitial(() -> {
        return new SimpleDateFormat("yyyyMMddHHmmssSSS");
    });
    private static String ip4;
    private int maxId = 0;
    private String bid;
    private Object lock = new Object();

    SegmentGen(String bid) {
        if (bid == null) {
            throw new NullPointerException("Invalid BID `" + bid + "`");
        } else {
            this.bid = bid;
        }
    }

    public String generate() {
        StringBuffer sb = new StringBuffer(32);
        sb.append(this.get17StringDate());
        sb.append(this.get4Bid(this.bid));
        sb.append(ip4);
        sb.append(this.get6Increase());
        sb.append(this.get1Random());
        String id = sb.toString();
        if (id.length() != 32) {
            throw new NullPointerException("generateBid32:生成id【" + id + "】长度异常，【bid】" + this.bid);
        } else {
            return id;
        }
    }

    private String get17StringDate() {
        Date currentTime = new Date();
        String dateString = ((SimpleDateFormat)threadLocalFormatter.get()).format(currentTime);
        return dateString;
    }

    private String get4Bid(String bid) {
        int len = bid.length();
        int max = 4;
        if (len >= max) {
            return bid;
        } else {
            StringBuffer sb = new StringBuffer(max);

            for(int i = 0; i < max - len; ++i) {
                sb.append("0");
            }

            sb.append(bid);
            return sb.toString();
        }
    }

    private String get6Increase() {
        DecimalFormat df = (DecimalFormat)threadLocalDecimalFormat.get();
        df.applyPattern("000000");
        synchronized(this.lock) {
            if (++this.maxId >= 999999) {
                this.maxId = 0;
            }

            return df.format((long)this.maxId);
        }
    }

    private String get1Random() {
        ThreadLocalRandom current = ThreadLocalRandom.current();
        return current.nextInt(10) + "";
    }

    static {
        try {
            InetAddress addr = InetAddress.getLocalHost();
            byte[] ip = addr.getAddress();
            StringBuilder st = new StringBuilder();

            for(int i = 2; i < ip.length; ++i) {
                String b = Integer.toHexString(255 & ip[i]);
                if (b.length() < 2) {
                    b = "0" + b;
                }

                st.append(b);
            }

            ip4 = st.toString();
        } catch (UnknownHostException var5) {
            ip4 = "000";
        }

    }
}
